package com.dubbo.common.file;

import com.alibaba.fastjson.JSON;
import com.dubbo.common.check.CheckUtil;
import com.dubbo.common.http.RequestUtil;
import com.dubbo.common.http.ResponseEntity;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.apache.commons.lang3.StringUtils;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient;

import java.io.*;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 文件处理工具类
 * 
 * @author chenwei
 * @date 2018年3月26日 下午8:48:44
 */
public final class FileUtil {
	
	private static final String FILE_SUFFIX = "png";
	
	/**
	 * 文件删除
	 * 
	 * @author chenwei
	 * @date 2018年3月26日 下午8:58:39
	 * @param url 文件url地址
	 * @param fastdfsUrl 文件存储服务器地址
	 * @param path cotroller层 this.getClass().getResource("/fastdfs_client.conf").getPath();
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("all") 
	public static boolean deleteFile(String url,String fastdfsUrl,String path) {
		try {
			ClientGlobal.init(path);

			StorageClient storageClient = new StorageClient();

			String urlRep = url.replace(fastdfsUrl, "");

			// 判断是url地址前面第一个字符是否是/符号
			boolean flag = true;
			while (flag) {
				if (urlRep.indexOf("/") == 0) {

					// 去掉url前面的/符号
					urlRep = urlRep.substring(1);
				}

				if (urlRep.indexOf("/") != 0) {
					flag = false;
				}

			}

			String prefixName = urlRep.substring(0, urlRep.indexOf("/"));
			String suffixName = urlRep.substring(urlRep.indexOf("/") + 1);

			if (StringUtils.isNotBlank(prefixName) && StringUtils.isNotBlank(suffixName)) {

				/**
				 * [group1, M00/00/00/wKgMgFlHqumASKsWAABonuLw4M4076.jpg] 数组中第一个元素：group1组的名称
				 * 数组中第二个元素：文件存储路径
				 */
				int res = storageClient.delete_file(prefixName, suffixName);
				// 删除成功res=2
				if (res != 2) {
					return false;
				}
			}
		} catch (Exception e) {
			return false;
		}
		return true;
	}
	
	/**
	 * 文件上传
	 * 
	 * @author chenwei
	 * @date 2018年5月21日 上午11:58:24
	 * @param path cotroller层 this.getClass().getResource("/fastdfs_client.conf").getPath();
	 * @param fileByte 文件字节数组
	 * @param fileName 文件名
	 * @return 如果返回值为空则上传失败
	 */
	public static String uploadFile(String path,byte[] fileByte,String fileName ) {
		try {
			ClientGlobal.init(path);
			StorageClient storageClient = new StorageClient();
			String[] arr = storageClient.upload_file(fileByte, 
					fileName, null);
			
			/** 拼接最后请求的地址 */
			StringBuilder url = new StringBuilder();
			for (String str : arr){
				url.append("/" + str);
			}
			return url.toString();
		}catch (Exception e) {
			e.printStackTrace();
		} 
		return null;
	}
	
	/**
	 * 读取本地文件转字节数组
	 * 
	 * @author chenwei
	 * @date 2018年5月21日 上午11:45:24
	 * @param filePath 文件路劲
	 * @return
	 * @throws IOException
	 */
	public static byte[] fileToByte(String filePath) throws IOException {
	    InputStream in = new FileInputStream(filePath);
	    byte[] data = toByteArray(in);
	    in.close();
	    
	    return data;
	}
	/**
	 * 输入流转数组
	 * 
	 * @author chenwei
	 * @date 2018年5月21日 上午11:43:36
	 * @param in
	 * @return
	 * @throws IOException
	 */
	private static byte[] toByteArray(InputStream in) throws IOException {
	 
	    ByteArrayOutputStream out = new ByteArrayOutputStream();
	    byte[] buffer = new byte[1024 * 8];
	    int n = 0;
	    while ((n = in.read(buffer)) != -1) {
	        out.write(buffer, 0, n);
	    }
	    return out.toByteArray();
	}
	/**
	 * 将url后戳封装成完整的url
	 * 
	 * @author chenwei
	 * @date 2018年6月3日 下午5:49:47
	 * @param urls
	 * @param urlPrefix
	 * @return
	 */
	public static List<String> packageFileUrl(List<String> urls,String urlPrefix){
		urls = urls.stream().map(url -> {
			if(!CheckUtil.checkUrl(url)) {
				return urlPrefix+url;
			}else {
				return url;
			}
		}).collect(Collectors.toList());
		return urls;
	}
	/**
	 * 将url后戳封装成完整的url
	 * 
	 * @author chenwei
	 * @date 2018年6月3日 下午6:17:26
	 * @param urlPrefix
	 * @param urls
	 * @return
	 */
	public static List<String> packageFileUrl2(String urlPrefix,String ...urls){
		List<String> asList = Arrays.asList(urls);
		asList = asList.stream().map(url -> {
			if(!CheckUtil.checkUrl(url)) {
				return urlPrefix+url;
			}else {
				return url;
			}
		}).collect(Collectors.toList());
		return asList;
	}
	/**
	 * 将url后戳封装成完整的url
	 * 
	 * @author chenwei
	 * @date 2018年6月3日 下午6:17:26
	 * @param urlPrefix
	 * @param urls
	 * @return
	 */
	public static String packageFileUrl3(String url,String urlPrefix){
		if(!CheckUtil.checkUrl(url)) {
			return urlPrefix+url;
		}else {
			return url;
		}
	}
	
	/**
	 * 生成二维码
	 * 
	 * @author chenwei
	 * @date 2018年7月2日 下午5:33:48
	 * @param path fastdfs配置文件路径 cotroller层 this.getClass().getResource("/fastdfs_client.conf").getPath();
	 * @param LocalPath 本地路径
	 * @param content 内容
	 * @param widthPix 高度
	 * @param heightPix 宽度
	 * @return
	 * @throws IOException
	 */
	public static String getQRCode(
			String path,
			String LocalPath,
			String content, 
			int widthPix, 
			int heightPix) throws IOException {
		try {
			if (!StringUtils.isNotBlank(content)) {
				return null;
			}
			//进行base64编码
			content = Base64.getEncoder().encodeToString(content.getBytes());
			// 配置参数
			Map<EncodeHintType, Object> hints = new HashMap<>();
			hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
			// 容错级别
			hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
			// 图像数据转换，使用了矩阵转换
			BitMatrix bitMatrix = new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, widthPix,
					heightPix, hints);
			int[] pixels = new int[widthPix * heightPix];
			// 下面这里按照二维码的算法，逐个生成二维码的图片，
			// 两个for循环是图片横列扫描的结果
			for (int y = 0; y < heightPix; y++) {
				for (int x = 0; x < widthPix; x++) {
					if (bitMatrix.get(x, y)) {
						pixels[y * widthPix + x] = 0xff000000;
					} else {
						pixels[y * widthPix + x] = 0xffffffff;
					}
				}
			}
			String fileName = UUID.randomUUID().toString().replaceAll("-", "");
			File file = new File(LocalPath+fileName+"."+FILE_SUFFIX);
			FileOutputStream fos = new FileOutputStream(file);
			MatrixToImageWriter.writeToStream(bitMatrix,FILE_SUFFIX,fos);
			byte[] fileToByte = FileUtil.fileToByte(LocalPath+fileName+"."+FILE_SUFFIX);
			//文件上传
			String uploadFile = FileUtil.uploadFile(path, fileToByte, "png");
			//删除本地文件
			file.deleteOnExit();
			fos.close();
			return uploadFile;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	
	/**
	 * 输入流转文件字节数组
	 * 
	 * @author chenwei
	 * @date 2018年7月5日 上午12:43:30
	 * @param is
	 * @return
	 * @throws IOException
	 */
	public static byte[] InputStreamToByte(InputStream is) throws IOException {
		ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int ch;
		/**
		 * 
		 * */
		while ((ch = is.read(buffer)) != -1) {
			bytestream.write(buffer, 0, ch);
		}
		byte data[] = bytestream.toByteArray();
		bytestream.close();
		is.close();
		return data;
	}
	/**
	 * 微信小程序获取二维码的方法
	 * <p>此方法调用的是小程序带参数跳转的B接口,详情请查看官方文档</p>
	 * <p>https://developers.weixin.qq.com/miniprogram/dev/api/qrcode.html</p>
	 * @author chenwei
	 * @date 2018年7月13日 下午9:54:21
	 * @param wxAccessTokenApi 小程序获取accessToken接口
	 * @param wxGrantType 一般是固定写法"client_credential"
	 * @param wxAppid 微信小程序appid
	 * @param wxSecret 微信小程序Secret
	 * @param wxAccessQrCodeApi 小程序获取二维码的接口 B接口
	 * @param content 二维码自定义参数
	 * @param wxPage 小程序页面路径 例如 "pages/index/index"必须是已经发布的小程序存在的页面（否则报错），
	 * @return
	 */
	public static InputStream getWxQrCodeParam(
			String wxAccessTokenApi,
			String wxGrantType,
			String wxAppid,
			String wxSecret,
			String wxAccessQrCodeApi,
			String content,
			String wxPage) {
			
		try {
			//如果没有则请求微信接口获取二维码
			String url = wxAccessTokenApi;
			Map<String, String> params = new HashMap<String, String>();
			params.put("grant_type", wxGrantType);
			params.put("appid", wxAppid); 
			params.put("secret", wxSecret);
			ResponseEntity httpClientGet;
			httpClientGet = RequestUtil.httpClientGet(url, params, null);
			Map<String, Object>  map = JSON.parseObject(httpClientGet.getContent());
			String access_token = map.get("access_token").toString();
			url = wxAccessQrCodeApi+access_token;
			params = new HashMap<String, String>();
			//设置设备的序列号
			params.put("scene", content);
			/**
			 * 必须是已经发布的小程序存在的页面（否则报错），
			 * 例如 "pages/index/index" ,
			 * 根路径前不要填加'/',
			 * 不能携带参数（参数请放在scene字段里），
			 * 如果不填写这个字段，默认跳主页面
			 */
			params.put("page", wxPage);
			return RequestUtil.httpClientPost2(url, params, null,true);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	public static void main(String[] args) throws Exception {
//		String path = FileUtil.class.getResource("/fastdfs_client.conf").getPath();
//		String qrCode = getQRCode(path, "g:/", "869300032262705", 800, 800);
//		System.out.println("qrCode"+qrCode);
		// http://img.infotoo.com.cn/group1/M00/00/00/rBJCgltFtiKAPDwsAAADVs5jXNs008.png
		FileInputStream fis = new FileInputStream(new File("C:\\Users\\Administrator\\Desktop\\招商加盟PF.pdf"));
		byte[] fileByte = FileUtil.InputStreamToByte(fis);
		String path = FileUtil.class.getResource("/fastdfs_client.conf").getPath();
		String uploadFile = FileUtil.uploadFile(path, fileByte, "pdf");
		System.out.println("http://img.gzyunjuli.com"+uploadFile);
		//http://img.gzyunjuli.com/group1/M00/00/01/rBLVTltQzD2AU3GxAB7pVwDmZGk022.pdf
	}
	
	//>>================================生成二维码==============================================
		/**
		 * 微信小程序获取二维码的方法
		 * <p>此方法调用的是小程序带参数跳转的B接口,详情请查看官方文档</p >
		 * <p>https://developers.weixin.qq.com/miniprogram/dev/api/qrcode.html</p >
		 * @author chenwei
		 * @date 2018年7月13日 下午9:54:21
		 * @param wxAccessTokenApi 小程序获取accessToken接口
		 * @param wxGrantType 一般是固定写法"client_credential"
		 * @param wxAppid 微信小程序appid
		 * @param wxSecret 微信小程序Secret
		 * @param wxAccessQrCodeApi 小程序获取二维码的接口 B接口
		 * @param content 二维码自定义参数
		 * @param wxPage 小程序页面路径 例如 "pages/index/index"必须是已经发布的小程序存在的页面（否则报错），
		 * @return
		 */
		public static InputStream getWxQrCodeParam2(
				String accessToken,
				String wxAccessQrCodeApi,
				String content,
				String wxPage) {
			
			try {
				//如果没有则请求微信接口获取二维码
				Map<String, String> params = new HashMap<String, String>();
				String url = wxAccessQrCodeApi+accessToken;
				params = new HashMap<String, String>();
				//设置设备的序列号
				params.put("scene", content);
				/**
				 * 必须是已经发布的小程序存在的页面（否则报错），
				 * 例如 "pages/index/index" ,
				 * 根路径前不要填加'/',
				 * 不能携带参数（参数请放在scene字段里），
				 * 如果不填写这个字段，默认跳主页面
				 */
				params.put("page", wxPage);
				return RequestUtil.httpClientPost3(url, params, null,true);
			} catch (Exception e) {
				e.printStackTrace();
				return null;
			}
		}
		//<<================================生成二维码==============================================
	
	 
}
